<?php

namespace GanYiInfo;

use GanYiInfo\Card\BankCardInterface;
use GanYiInfo\Card\IdCard;
use GanYiInfo\Contracts\ArrayAble;
use GanYiInfo\Utils\Str;

class RequestParameter implements ArrayAble
{
    /**
     * @var \SplObjectStorage
     */
    private $creditCards;

    /**
     * @var \SplObjectStorage
     */
    private $debitCards;

    /**
     * @var null|IdCard
     */
    private $idCard = null;

    private $mobile;

    private $sign;

    private $merNo;

    private $timestamp;

    private $randomStr;

    /**
     * RequestParameter constructor.
     * @param $merNo
     * @throws \Exception
     */
    public function __construct($merNo)
    {
        $this->merNo = $merNo;
        $this->timestamp = date("Y-m-d H:i:s");
        $this->randomStr = Str::random(32);
        $this->creditCards = new \SplObjectStorage();
        $this->debitCards = new \SplObjectStorage();
    }

    /**
     * @param $mobile
     * @throws \Exception
     */
    public function setMobile($mobile)
    {
        if (!Str::isMobile($mobile)) {
            throw new \Exception("Mobile incorrect.");
        }

        $this->mobile = $mobile;
    }

    /**
     * @param $sign
     */
    public function setSign($sign)
    {
        $this->sign = $sign;
    }

    /**
     * @param BankCardInterface $card
     */
    public function addCreditCard(BankCardInterface $card)
    {
        $this->creditCards->attach($card);
    }

    /**
     * @param BankCardInterface $card
     */
    public function addDebitCard(BankCardInterface $card)
    {
        $this->debitCards->attach($card);
    }

    /**
     * @param IdCard $idCard
     */
    public function setIdCard(IdCard $idCard)
    {
        $this->idCard = $idCard;
    }

    /**
     * @return array
     * @throws \Exception
     */
    public function toArray()
    {
        if (Str::checkEmpty($this->merNo)) {
            throw new \Exception("MerNo is required.");
        }

        if ($this->idCard === null && ($this->creditCards->count() > 0 || $this->debitCards->count() > 0)) {
            throw new \Exception("IDCard is required when creditCard or debitCard added.");
        }

        $creditCards = $this->getCreditCardArray();
        $debitCards = $this->getDebitCardArray();
        $params = [
            "mer_no" => $this->merNo,
            "mobile" => $this->mobile,
            "random_str" => $this->randomStr,
            "timestamp" => $this->timestamp
        ];

        if ($this->idCard !== null) {
            $params["idcard"] = $this->idCard->toArray();
        }

        if ($this->creditCards->count() > 0) {
            $params["creditcards"] = $creditCards;
        }

        if ($this->debitCards->count() > 0) {
            $params["debitcards"] = $debitCards;
        }

        if (!Str::checkEmpty($this->sign)) {
            $params["sign"] = $this->sign;
        }

        return $params;
    }

    /**
     * @return IdCard|null
     */
    public function getIdCard()
    {
        return $this->idCard;
    }

    /**
     * @return array
     */
    public function getCreditCardArray()
    {
        $cards = [];

        foreach ($this->creditCards as $card) {
            $cards[] = $card->toArray();
        }

        return $cards;
    }

    /**
     * @return array
     */
    public function getDebitCardArray()
    {
        $cards = [];

        foreach ($this->debitCards as $card) {
            $cards[] = $card->toArray();
        }

        return $cards;
    }
}